
#ifndef _ENGINEOBJECT_H_
#define _ENGINEOBJECT_H_

#include "refBase.h"


class EngineObject;


/// Declare an abstract class @a type derived from the class @a super.
///
/// @code
/// class MyClass : public EngineObject
/// {
///     DECLARE_ABSTRACT_CLASS( MyClass, EngineObject );
/// };
/// @endcode
///
/// @param type C++ class type.
/// @param super C++ class type of the superclass.  May be void only for EngineObject.
///
/// @see IMPLEMENT_NONINSTANTIABLE_CLASS
#define DECLARE_ABSTRACT_CLASS( type, super )                                          \
   public:                                                                             \
      typedef type ThisType;                                                           \
      typedef super SuperType;                                                         \
      template< typename T > friend struct ::_EngineTypeTraits;                        \
      template< typename T > friend struct ::_SCOPE;                                   \
      template< typename T > friend T* _CREATE();                                      \
      template< typename T, typename Base > friend class ::EngineClassTypeInfo;        \
   private:                                                                            \
      typedef ::_Private::_AbstractClassBase< ThisType > _ClassBase;                   \
      static EngineClassTypeInfo< ThisType, _ClassBase > _smTypeInfo;                  \
      static EngineExportScope& __engineExportScope();                                 \
      static EnginePropertyTable& _smPropertyTable;                                    \
      virtual const EngineTypeInfo* __typeinfo() const;                                \
   public:




/// Assign the current class and all its subclasses to the given export scope.
/// May be overridden by subclasses.
///
/// @code
/// class MyClass : public EngineObject
/// {
///     DECLARE_CLASS( MyClass, EngineObject );
///     DECLARE_INSCOPE( MyAPI );
/// };
/// @endcode
#define DECLARE_INSCOPE( name )                                                        \
   typedef name __DeclScope;

/// Declare that this class and all its subclasses can be instantiated through the
/// API using their respective create() functions.
///
/// May be overridden by subclasses.
///
/// @code
/// class MyClass : public EngineObject
/// {
///     DECLARE_CLASS( MyClass, EngineObject );
///     DECLARE_INSTANTIABLE;
/// };
/// @endcode
#define DECLARE_INSTANTIABLE                                                           \
   typedef ::TrueType __IsInstantiableType;




/// Base class for all objects that may be passed to the control layer.
///
/// A set of rules applies to all EngineObject-derived classes:
///
/// - Every EngineObject class must have a default constructor.
/// - The default constructor and the destructor of every EngineObject class must be public.
/// - If an EngineObject class inherits from multiple classes, the class leading back to EngineObject
///   must be the @b first class in the list to ensure binary-compatible class layouts.
/// - EngineObjects are cooperatively reference-counted by both the engine as well as the control
///   layer.
//class EngineObject : public StrongRefBase
//{
//   public:
//
//      DECLARE_ABSTRACT_CLASS( EngineObject, void );
//      DECLARE_INSCOPE( _GLOBALSCOPE );
//      DECLARE_INSTANTIABLE;
//
//      friend const EngineTypeInfo* TYPEOF( const EngineObject* ); // __typeinfo
//      friend void*& _USERDATA( EngineObject* ); // mEngineObjectUserData
//      friend class StaticEngineObject; // mEngineObjectPool
//
//   protected:
//
//      typedef ::FalseType __IsDisposableType;
//      typedef ::FalseType __IsSingletonType;
//
//      DEFINE_CREATE_METHOD
//      {
//         T* object = new T;
//         object->incRefCount();
//         return object;
//      }
//
//      /// Subclasses should overload this method instead of the public destroySelf().
//      virtual void _destroySelf() {}
//
//      ///
//      static void* _allocateObject( size_t size, IEngineObjectPool* pool TORQUE_TMM_ARGS_DECL );
//
//   public:
//
//      EngineObject();
//      virtual ~EngineObject();
//
//      /// Return a string that describes this instance.  Meant primarily for debugging.
//      virtual String describeSelf() const;
//
//      #ifndef TORQUE_DISABLE_MEMORY_MANAGER
//      // Make sure no matter what, we get the new/delete calls.
//      void* operator new( size_t size );
//      void* operator new( size_t size, IEngineObjectPool* pool );
//      #endif
//
//      /// Allocate a new object in the default object pool.
//      /// @param size Size of the object in bytes.
//      /// @return Memory block for new object; never NULL.
//      void* operator new( size_t size TORQUE_TMM_ARGS_DECL );
//
//      /// Allocate a new object in the given object pool.
//      ///
//      /// If the given pool's allocateObject returns NULL, the method will fall back
//      /// to the default pool.
//      ///
//      /// @param size Size of the object in bytes.
//      /// @param pool Object pool to allocate the object in.
//      /// @return Memory block for the new object; never NULL.
//      void* operator new( size_t size, IEngineObjectPool* pool TORQUE_TMM_ARGS_DECL );
//
//      /// Placement new.
//      void* operator new( size_t size, void* ptr ) { return ptr; }
//
//      /// Release the given object's memory in the pool it has been allocated from.
//      void operator delete( void* ptr );
//
//      /// Return the pool of EngineObjects to which this object belongs.
//      IEngineObjectPool* getEngineObjectPool() const { return mEngineObjectPool; }
//
//      // StrongRefBase
//      virtual void destroySelf();
//
//#ifdef TORQUE_DEBUG
//
//      /// @name Instance Tracking (debugging only)
//      ///
//      /// In debug builds, all EngineObjects are kept on a global list so that it is easy
//      /// to enumerate all live objects at any time.
//      ///
//      /// @note This is @b NOT thread-safe.
//      /// @{
//
//      /// Type of callback function for iterating over EngineObject instances.
//      typedef void ( *DebugEnumInstancesCallback )( EngineObject* );
//
//      /// Dump describeSelf()s of all live ConsoleObjects to the console.
//      static void debugDumpInstances();
//
//      /// Call the given callback for all instances of the given type.
//      /// Callback may also be NULL in which case the method just iterates
//      /// over all instances of the given type.  This is useful for setting
//      /// a breakpoint during debugging.
//      static void debugEnumInstances( const std::type_info& type, DebugEnumInstancesCallback callback );
//
//      /// Same as above but uses an export class name and also includes
//      /// inheritance (i.e. enumerates all instances of the given class and
//      /// its subclasses).
//      static void debugEnumInstances( const char* className, DebugEnumInstancesCallback callback );
//
//   private:
//
//      /// Next object in global link chain of engine objects.
//      /// @note Debug builds only.
//      EngineObject* mNextEngineObject;
//
//      /// Previous object in global link chain of engine objects.
//      /// @note Debug builds only.
//      EngineObject* mPrevEngineObject;
//
//      /// Total number of engine objects currently instantiated.
//      /// @note Debug builds only.
//      static U32 smNumEngineObjects;
//
//      /// First object in the global link chain of engine objects.
//      /// @note Debug builds only.
//      static EngineObject* smFirstEngineObject;
//
//      /// @}
//
//#endif
//
//   private:
//
//      /// Object pool to which this object belongs.  If this is NULL,
//      /// the object will not deallocate itself when it is destructed.
//      /// This is useful for inline allocation of objects.
//      IEngineObjectPool* mEngineObjectPool;
//
//      /// Opaque user data pointer that the control layer may install
//      /// on any engine object.  Most importantly, this allows control layers
//      /// to very easily keep track of EngineObjects that they have already
//      /// created their own wrapper objects for.
//      void* mEngineObjectUserData;
//
//      // Disable array new/delete operators.
//      void* operator new[]( size_t );
//      void operator delete[]( void* );
//};

#endif // !_ENGINEOBJECT_H_
